use axum::Json;
use serde::Serialize;

use crate::helper::{errcode_to_i32, ErrCode};


#[derive(Debug, Default, Serialize)]
pub struct ApiResponse<T: Serialize = ()> {
    #[serde(serialize_with = "errcode_to_i32")]
    code: ErrCode,
    #[serde(rename = "errMsg")] 
    err_msg: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    data: Option<T>,
    #[serde(skip_serializing_if = "Option::is_none")]
    page: Option<ApiPagination>,
}

/// ### http 接口 Response 包装为 json
/// - code: ErrCode
/// - msg: String
/// - data: Option<T>
pub type JsonRes<T> = Json<ApiResponse<T>>;
pub type DefaultRes = JsonRes<()>;

#[derive(Debug, Default, Serialize)]
pub struct ApiPagination {
    #[serde(skip_serializing_if = "Option::is_none")]
    total: Option<i32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    page: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    size: Option<u32>,
}

pub struct DefaultApiResponse {
    code: ErrCode,
    err_msg: String,
}

impl<T: Serialize> ApiResponse<T> {
    pub fn new(code: ErrCode, err_msg: String, data: T, page: Option<ApiPagination>) -> Self {
        Self {
            code,
            err_msg,
            data: Some(data),
            page,
        }
    }

    pub fn default() -> Self {
        Self {
            code: ErrCode::default(),
            err_msg: "".to_string(),
            data: None,
            page: None,
        }
    }

    pub fn json() -> JsonRes<T> {
        Json(Self::default())
    }
}
